package models

import "reflect"
import "strings"
import "encoding/json"
import "github.com/beego/beego/v2/client/orm"
import "beergo/lib/base/repository"
import "beergo/lib/mysql"
import "beergo/lib/tool"
import "github.com/beego/beego/v2/client/orm/hints"


func init() {
    //orm.RegisterModel(new(Doctor))
    orm.RegisterModelWithPrefix("check_", new(Doctor))
}

func (this *Doctor) GetReflect() reflect.Type {
    return reflect.TypeOf(Doctor{})
}
func (this Doctor) New() *Doctor {
    model := new(Doctor)
    model.SetCtx(this.GetCtx())
    //event.DispatchToMany("DoctorNew", model, this.GetCtx())
    this.Trigger("check.DoctorNew",model)
    return model
}
func (this *Doctor) Read(fields ...string) *Doctor {
    this.GetOrm().Read(this, fields...)
    return this
}
func (this *Doctor) Load(name string) *Doctor {
    this.GetOrm().LoadRelated(this, name)
    return this
}
func (this *Doctor) Save(fields ...string) (int64, error) {
    var id int64
    if this.Id == 0 {
        //event.DispatchToMany("check.BeforeDoctorCreate", this, this.GetCtx())
        this.Trigger("check.BeforeDoctorCreate",this)
        id, err := this.GetOrm().Insert(this)
        if err != nil {
            return id, err
        }
        //event.DispatchToMany("check.AfterDoctorCreate", this, this.GetCtx())
        this.Trigger("check.AfterDoctorCreate",this)
    } else {
        //event.DispatchToMany("check.BeforeDoctorUpdate", this, this.GetCtx())
        this.Trigger("check.BeforeDoctorUpdate",this)
        id, err := this.GetOrm().Update(this, fields...)
        if err != nil {
            return id, err
        }
        //event.DispatchToMany("check.AfterDoctorUpdate", this, this.GetCtx())
        this.Trigger("check.AfterDoctorUpdate",this)
    }
    return id, nil
}
func (this *Doctor) Delete() (int64, error) {
    //event.DispatchToMany("check.DoctorDelete", this, this.GetCtx())
    this.Trigger("check.DoctorDelete",this)
    return this.GetOrm().Delete(this)
}
func (this *Doctor) CreateFromObject(jsonData interface{}) *Doctor {
    tableByte, err := json.Marshal(jsonData)
    if err != nil {println(err.Error())}
    err = json.Unmarshal(tableByte, this)
    if err != nil {println(err.Error())}
    return this
}
func (this *Doctor) CreateFromString(jsonString string) *Doctor {
    err := json.Unmarshal([]byte(jsonString), this)
    if err != nil {println(err.Error())}
    return this
}
func (this *Doctor) ToString() string {
    ret, err := json.Marshal(this)
    if err != nil {println(err.Error())}
    return string(ret)
}
func (this *Doctor) FillList(name string, ids []int) orm.Ormer {
    o := orm.NewOrm()
    if this.Id == 0 {
        this.Save()
    }
    //__M2M_FILL__
    return o
}
func (this *Doctor) ToArray(fields string) map[string]interface{} {
    var data = make(map[string]interface{})
    if fields== "" || tool.HasSameWord(fields,"id") {
    data["id"] = this.Id
    }
    //__TO_ARRAY_FILL__
    if fields== "" ||  tool.HasSameWord(fields, "user") {
        if this.User !=nil {
            this.User.Read()
        }
        data["user"] = this.User
    }
    if fields== "" ||  tool.HasSameWord(fields, "name") {
        data["name"] = this.Name
    }
    if fields== "" ||  tool.HasSameWord(fields, "pic") {
        data["pic"] = this.Pic
    }
    if fields== "" ||  tool.HasSameWord(fields, "level") {
        data["level"] = this.Level
    }
    if fields== "" ||  tool.HasSameWord(fields, "info") {
        data["info"] = this.Info
    }
    if fields== "" ||  tool.HasSameWord(fields, "content") {
        data["content"] = this.Content
    }
    return data
}
func (this *Doctor) ToArrayEdit() map[string]interface{} {
    var data = make(map[string]interface{})
    data["id"] = this.Id
    //__EDIT_FILL__
    if this.User == nil {
        data["user"] = ""
    }else {
        data["user"] = this.User.Id
    }
    data["name"] = this.Name
    data["pic"] = this.Pic
    data["level"] = this.Level
    data["info"] = this.Info
    data["content"] = this.Content
    return data
}
func (this *Doctor) Scan(fields string,depth int,parent string) map[string]interface{} {
    var data = make(map[string]interface{})
    if fields== "" || tool.HasSameWord(fields, parent + "id") {
        data["id"] = this.Id
    }
    //__SCAN_FILL__
    if fields== "" || tool.HasSameWord(fields, parent + "user") {
        //this.GetOrm().LoadRelated(this,"user")
        if depth >0  && this.User != nil {
        this.User.Read()
            data["user"] = this.User.Scan(fields,depth-1,"user.")
        }else {
            data["user"] = this.User
        }
    }
    if fields== "" ||  tool.HasSameWord(fields,  parent + "name") {
        data["name"] = this.Name
    }
    if fields== "" ||  tool.HasSameWord(fields,  parent + "pic") {
        data["pic"] = this.Pic
    }
    if fields== "" ||  tool.HasSameWord(fields,  parent + "level") {
        data["level"] = this.Level
    }
    if fields== "" ||  tool.HasSameWord(fields,  parent + "info") {
        data["info"] = this.Info
    }
    if fields== "" ||  tool.HasSameWord(fields,  parent + "content") {
        data["content"] = this.Content
    }
    return data
}


/***************************************
Repository
****************************************/
type DoctorRepository struct {
    repository.BaseRepository
}

func (this *DoctorRepository) GetQuerySetter() orm.QuerySeter {
    o := orm.NewOrm().QueryTable(Doctor{})
    if this.IsLoadRelation {
        o = o.RelatedSel()
    }
    return o
}
func (rep DoctorRepository) Find(id int) Doctor {
    filter := tool.DbCreateFilter()
    filter["Id"] = id
    return rep.FindOneBy(filter, nil)
}

func (rep DoctorRepository) FindOneBy(filters map[string]interface{}, orderbys []string) Doctor {
    var model Doctor
    qs := rep.GetQuerySetter()
    for key, item := range filters {
        qs = qs.Filter(key, item)
    }
    qs = qs.OrderBy(orderbys...)
    err := qs.Limit(1).One(&model)
    if err != nil {
        //todo
    }
    return model
}

func (rep DoctorRepository) FindBy(filters map[string]interface{}, orderbys []string, limit int, offset int) ([]Doctor, int64) {
    var models []Doctor
    qs := rep.GetQuerySetter()
    for key, item := range filters {
        qs = qs.Filter(key, item)
    }
    qs = qs.OrderBy(orderbys...)
    count, err := qs.Limit(limit).Offset(offset).All(&models)
    if err != nil {
        //todo
        print(count)
    }
    return models, count
}

func (rep DoctorRepository) CountBy(filters map[string]interface{}) int {
    qs := rep.GetQuerySetter()
    for key, item := range filters {
        qs = qs.Filter(key, item)
    }
    count, err := qs.Count()
    if err != nil {
        //todo
        print(count)
    }
    return tool.Int64ToInt(count)
}
func (rep DoctorRepository) FindAll(orderbys []string) ([]Doctor, int64) {
    var all []Doctor
    count, err := rep.GetQuerySetter().OrderBy(orderbys...).All(&all)
    if err != nil {
        //todo
        print(count)
    }
    return all, count
}

func (rep DoctorRepository) ListCount(filters map[string]interface{}) int {
    return rep.CountBy(filters)
}

func (rep DoctorRepository) ListAdmin(filters map[string]interface{}, orderbys []string, limit int, offset int) ([]Doctor, int64) {
    return rep.FindBy(filters, orderbys, limit, offset)
}

func (rep DoctorRepository) ListApi(filters map[string]interface{}, orderbys []string, limit int, offset int) ([]Doctor, int64) {
    return rep.FindBy(filters, orderbys, limit, offset)
}
func (rep DoctorRepository) ListCategory(Tree []map[string]interface{}, RootId int, startLevel int) []map[string]interface{} {
    where := tool.StringKeyMap{}
    if RootId == 0 {
        where["parent__isnull"] = true
    } else {
        where["parent"] = RootId
    }
    order := []string{"sort"}
    roots, _ := rep.FindBy(where, order, 0, 0)
    for _, root := range roots {
        prefix := ""
        if startLevel > 0 {
            prefix = "├"
        }
        name := reflect.ValueOf(root).FieldByName("Name").String()
        Tree = append(Tree, map[string]interface{}{
            "id":    root.Id,
            "value": prefix + strings.Repeat("╌╌", startLevel) + name,
        })
        rep.GetOrm().LoadRelated(&root, "Children")
        Tree = rep.ListCategory(Tree, root.Id, startLevel+1)
    }
    return Tree
}

/******************新增加的相关功能*************************/
func (rep DoctorRepository) Get(id int, builder *mysql.QueryBuilder) (*Doctor, error) {
    builder.Conditions["id"] = id
    return rep.GetOne(builder)
}

func (rep DoctorRepository) GetOne(builder *mysql.QueryBuilder) (*Doctor, error) {
    var model = new(Doctor)
    builder.Limit = 1
    builder.Page = 1
    qs := rep.PrepareQuery(builder)
    builder.MakeFields()
    fieldsOne:=rep.GetRelationStringOne(builder,&Doctor{})
    if len(fieldsOne)>0 {
        qs = qs.RelatedSel(fieldsOne...)
    }
    err := qs.One(model, builder.GetFields()...)
    if err != nil {
        return nil, err
    }

    fieldsMany:=rep.GetRelationStringMany(builder,&Doctor{})
    if len(fieldsMany) >0 {
        for _, f := range fieldsMany {
            _,err:=rep.GetOrm().LoadRelated(model,f)
            if err !=nil {
                //return nil, err
            }
        }
    }
    return model, nil
}
func (rep DoctorRepository) GetList(builder *mysql.QueryBuilder) ([]*Doctor, error) {
    //ormer:= orm.NewOrm()
    o := rep.PrepareQuery(builder)
    builder.MakeFields()
    fieldsOne:=rep.GetRelationStringOne(builder,&Doctor{})
    if len(fieldsOne)>0 {
        o = o.RelatedSel(fieldsOne...)
    }
    var data []*Doctor
    _, err := o.All(&data, builder.GetFields()...)
    if err != nil {
        return nil, err
    }
    total, err := rep.Count(builder)
    if err != nil {
        return nil, err
    }
    builder.Total = total
    fieldsMany:=rep.GetRelationStringMany(builder,&Doctor{})
    if len(fieldsMany) >0 {
        for _, f := range fieldsMany {
            for _, row := range data {
                _,err:=rep.GetOrm().LoadRelated(row,f)
                if err !=nil {
                    //return nil, err
                }
            }
        }
    }
    return data, nil
}

func (rep DoctorRepository) Count(builder *mysql.QueryBuilder) (int64, error) {
    qs := rep.PrepareQuery(builder)
    count, err := qs.Count()
    if err != nil {
        return 0, err
    }
    return count, nil
}

func (rep DoctorRepository) PrepareQuery(builder *mysql.QueryBuilder) orm.QuerySeter {
    o := orm.NewOrm().QueryTable(Doctor{})
    for key, item := range builder.GetFilter() {
        o = o.Filter(key, item)
    }
    for key, item := range builder.GetExclude() {
        o = o.Exclude(key, item)
    }
    searchConf := rep.CreateSearch(builder)
    if searchConf !=nil {
        o = o.SetCond(searchConf)
    }
    builder.MakeFields()
    o = o.OrderBy(builder.GetOrder()...).
        Limit(builder.GetLimit()).
        Offset(builder.GetOffset())
    return o
}

func (rep DoctorRepository) neverUsedInRep(){
    c:=hints.Hint{}
    print(&c)
}
